#!/bin/bash

# ============================================================
# OHOS 测试服务器 - 云服务器一键部署脚本
# 用途：在云服务器上快速部署所有测试服务器
# 使用: ./cloud-deploy.sh [IP地址]
# 示例: ./cloud-deploy.sh 120.46.148.42
# ============================================================

set -e

# 颜色定义
RESET='\033[0m'
GREEN='\033[32m'
YELLOW='\033[33m'
CYAN='\033[36m'
RED='\033[31m'
BOLD='\033[1m'

echo -e "${CYAN}============================================${RESET}"
echo -e "${CYAN}  OHOS 测试服务器 - 云服务器部署${RESET}"
echo -e "${CYAN}============================================${RESET}"
echo ""

# 检查是否通过参数传入IP地址
SERVER_IP=""
if [ -n "$1" ]; then
    SERVER_IP="$1"
    echo -e "${CYAN}📍 使用指定的服务器IP: ${GREEN}${SERVER_IP}${RESET}"
    echo ""
fi

# 检查是否在云服务器上
if [ -z "$SERVER_IP" ]; then
    echo -e "${CYAN}📍 检测环境...${RESET}"
    
    # 尝试多种方式获取公网IP（带超时）
    PUBLIC_IP=""
    if command -v curl &> /dev/null; then
        PUBLIC_IP=$(curl -s --connect-timeout 3 --max-time 5 ifconfig.me 2>/dev/null || \
                    curl -s --connect-timeout 3 --max-time 5 icanhazip.com 2>/dev/null || \
                    curl -s --connect-timeout 3 --max-time 5 api.ipify.org 2>/dev/null)
    elif command -v wget &> /dev/null; then
        PUBLIC_IP=$(wget -qO- --timeout=5 ifconfig.me 2>/dev/null || \
                    wget -qO- --timeout=5 icanhazip.com 2>/dev/null)
    fi
    
    # 如果无法获取公网IP，尝试获取本地IP
    if [ -z "$PUBLIC_IP" ]; then
        PUBLIC_IP=$(hostname -I 2>/dev/null | awk '{print $1}')
        [ -z "$PUBLIC_IP" ] && PUBLIC_IP=$(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | grep -v '127.0.0.1' | head -1)
        [ -z "$PUBLIC_IP" ] && PUBLIC_IP="localhost"
        echo -e "   本地IP: ${YELLOW}${PUBLIC_IP}${RESET} ${RED}(无法获取公网IP)${RESET}"
    else
        echo -e "   公网IP: ${GREEN}${PUBLIC_IP}${RESET}"
    fi
    
    SERVER_IP="$PUBLIC_IP"
    echo ""
else
    # 使用传入的IP作为PUBLIC_IP用于后续显示
    PUBLIC_IP="$SERVER_IP"
fi

# 检查 Docker 是否安装
echo -e "${CYAN}🔍 检查 Docker...${RESET}"
if ! command -v docker &> /dev/null; then
    echo -e "${YELLOW}❌ Docker 未安装${RESET}"
    echo ""
    read -p "是否自动安装 Docker? (y/N): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        echo -e "${CYAN}📦 安装 Docker...${RESET}"
        curl -fsSL https://get.docker.com | bash
        sudo systemctl start docker
        sudo systemctl enable docker
        sudo usermod -aG docker $USER
        echo -e "${GREEN}✅ Docker 安装完成${RESET}"
        echo -e "${YELLOW}⚠️  请重新登录以使 Docker 组权限生效${RESET}"
        echo -e "${YELLOW}   然后重新运行此脚本${RESET}"
        exit 0
    else
        echo -e "${RED}❌ 需要 Docker 才能继续部署${RESET}"
        exit 1
    fi
else
    echo -e "${GREEN}✅ Docker 已安装${RESET}"
    docker --version
fi
echo ""

# 检查 Docker Compose
echo -e "${CYAN}🔍 检查 Docker Compose...${RESET}"
if ! command -v docker-compose &> /dev/null; then
    echo -e "${YELLOW}❌ Docker Compose 未安装${RESET}"
    echo ""
    read -p "是否自动安装 Docker Compose? (y/N): " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        echo -e "${CYAN}📦 安装 Docker Compose...${RESET}"
        sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
        sudo chmod +x /usr/local/bin/docker-compose
        echo -e "${GREEN}✅ Docker Compose 安装完成${RESET}"
    else
        echo -e "${YELLOW}⚠️  将使用 docker compose 命令（Docker 内置）${RESET}"
    fi
else
    echo -e "${GREEN}✅ Docker Compose 已安装${RESET}"
    docker-compose --version
fi
echo ""

# 选择部署方式
echo -e "${CYAN}============================================${RESET}"
echo -e "${CYAN}  选择部署方式${RESET}"
echo -e "${CYAN}============================================${RESET}"
echo ""
echo "  1) Docker Compose（推荐 - 一键部署）"
echo "  2) Docker 命令（手动控制）"
echo "  3) 本地运行（不使用容器）"
echo ""
read -p "请选择 (1/2/3) [1]: " DEPLOY_MODE
DEPLOY_MODE=${DEPLOY_MODE:-1}
echo ""

case $DEPLOY_MODE in
    1)
        echo -e "${CYAN}============================================${RESET}"
        echo -e "${CYAN}  使用 Docker Compose 部署${RESET}"
        echo -e "${CYAN}============================================${RESET}"
        echo ""
        
        # 生成证书（包括客户端证书）
        echo -e "${CYAN}📝 生成证书 (服务器IP: ${SERVER_IP})...${RESET}"
        mkdir -p cert
        cd cert
        
        # 生成服务器证书
        if [ ! -f "server.crt" ]; then
            # 构建 SAN 扩展（包含服务器IP）
            SAN_EXT="DNS:localhost,DNS:*.local,IP:127.0.0.1,IP:0.0.0.0"
            if [ "$SERVER_IP" != "localhost" ] && [ "$SERVER_IP" != "127.0.0.1" ]; then
                SAN_EXT="${SAN_EXT},IP:${SERVER_IP}"
            fi
            
            openssl req -x509 -newkey rsa:2048 -nodes \
                -keyout server.key -out server.crt -days 365 \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS/CN=${SERVER_IP}" \
                -addext "subjectAltName=${SAN_EXT}" 2>/dev/null
            echo -e "${GREEN}✅ 服务器证书生成完成 (IP: ${SERVER_IP})${RESET}"
        else
            echo -e "${GREEN}✅ 服务器证书已存在${RESET}"
        fi
        
        # 创建 ca.crt（用于双向认证）
        if [ ! -f "ca.crt" ]; then
            cp server.crt ca.crt
            cp server.key ca.key
            echo -e "${GREEN}✅ CA证书创建完成 (复制自server.crt)${RESET}"
        fi
        
        # 生成客户端证书（由CA签发）
        if [ ! -f "client.crt" ]; then
            # 生成客户端私钥和CSR
            openssl req -newkey rsa:2048 -nodes \
                -keyout client.key \
                -out client.csr \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS Client/CN=client" 2>/dev/null
            
            # 使用CA签发客户端证书
            openssl x509 -req -in client.csr \
                -CA ca.crt -CAkey ca.key \
                -CAcreateserial -out client.crt \
                -days 365 2>/dev/null
            
            # 生成带密码的客户端私钥（密码: 123456）
            openssl rsa -des3 -in client.key -out client_encrypted.key -passout pass:123456 2>/dev/null
            
            # 生成无密码的 P12 证书包（用于 4003 端口）
            openssl pkcs12 -export -out client.p12 \
                -inkey client.key \
                -in client.crt \
                -certfile ca.crt \
                -passout pass: 2>/dev/null
            
            # 生成带密码的 P12 证书包（用于 4002 端口，密码: 123456）
            # 使用加密的私钥 client_encrypted.key，需要 -passin 读取私钥密码
            openssl pkcs12 -export -out client_encrypted.p12 \
                -inkey client_encrypted.key \
                -passin pass:123456 \
                -in client.crt \
                -certfile ca.crt \
                -passout pass:123456 2>/dev/null
            
            # 清理临时文件
            rm -f client.csr ca.srl
            
            echo -e "${GREEN}✅ 客户端证书生成完成 (由CA签发)${RESET}"
            echo -e "${CYAN}   无密码版本: client.key, client.p12 (用于 4003 端口)${RESET}"
            echo -e "${CYAN}   带密码版本: client_encrypted.key, client_encrypted.p12 (用于 4002 端口, 密码: 123456)${RESET}"
        else
            echo -e "${GREEN}✅ 客户端证书已存在${RESET}"
        fi
        
        cd ..
        echo ""
        
        # 构建并启动
        echo -e "${CYAN}🔨 构建镜像并启动容器...${RESET}"
        if command -v docker-compose &> /dev/null; then
            docker-compose up -d --build
        else
            docker compose up -d --build
        fi
        
        echo ""
        echo -e "${GREEN}✅ 部署成功！${RESET}"
        echo ""
        echo -e "${CYAN}📋 查看状态:${RESET}"
        if command -v docker-compose &> /dev/null; then
            docker-compose ps
        else
            docker compose ps
        fi
        echo ""
        echo -e "${CYAN}📊 查看日志:${RESET}"
        echo -e "   docker-compose logs -f"
        echo ""
        ;;
        
    2)
        echo -e "${CYAN}============================================${RESET}"
        echo -e "${CYAN}  使用 Docker 命令部署${RESET}"
        echo -e "${CYAN}============================================${RESET}"
        echo ""
        
        # 生成证书（包括客户端证书）
        echo -e "${CYAN}📝 生成证书 (服务器IP: ${SERVER_IP})...${RESET}"
        mkdir -p cert
        cd cert
        
        # 生成服务器证书
        if [ ! -f "server.crt" ]; then
            # 构建 SAN 扩展（包含服务器IP）
            SAN_EXT="DNS:localhost,DNS:*.local,IP:127.0.0.1,IP:0.0.0.0"
            if [ "$SERVER_IP" != "localhost" ] && [ "$SERVER_IP" != "127.0.0.1" ]; then
                SAN_EXT="${SAN_EXT},IP:${SERVER_IP}"
            fi
            
            openssl req -x509 -newkey rsa:2048 -nodes \
                -keyout server.key -out server.crt -days 365 \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS/CN=${SERVER_IP}" \
                -addext "subjectAltName=${SAN_EXT}" 2>/dev/null
            echo -e "${GREEN}✅ 服务器证书生成完成 (IP: ${SERVER_IP})${RESET}"
        else
            echo -e "${GREEN}✅ 服务器证书已存在${RESET}"
        fi
        
        # 创建 ca.crt（用于双向认证）
        if [ ! -f "ca.crt" ]; then
            cp server.crt ca.crt
            cp server.key ca.key
            echo -e "${GREEN}✅ CA证书创建完成 (复制自server.crt)${RESET}"
        fi
        
        # 生成客户端证书（由CA签发）
        if [ ! -f "client.crt" ]; then
            # 生成客户端私钥和CSR
            openssl req -newkey rsa:2048 -nodes \
                -keyout client.key \
                -out client.csr \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS Client/CN=client" 2>/dev/null
            
            # 使用CA签发客户端证书
            openssl x509 -req -in client.csr \
                -CA ca.crt -CAkey ca.key \
                -CAcreateserial -out client.crt \
                -days 365 2>/dev/null
            
            # 生成带密码的客户端私钥（密码: 123456）
            openssl rsa -des3 -in client.key -out client_encrypted.key -passout pass:123456 2>/dev/null
            
            # 生成无密码的 P12 证书包（用于 4003 端口）
            openssl pkcs12 -export -out client.p12 \
                -inkey client.key \
                -in client.crt \
                -certfile ca.crt \
                -passout pass: 2>/dev/null
            
            # 生成带密码的 P12 证书包（用于 4002 端口，密码: 123456）
            # 使用加密的私钥 client_encrypted.key，需要 -passin 读取私钥密码
            openssl pkcs12 -export -out client_encrypted.p12 \
                -inkey client_encrypted.key \
                -passin pass:123456 \
                -in client.crt \
                -certfile ca.crt \
                -passout pass:123456 2>/dev/null
            
            # 清理临时文件
            rm -f client.csr ca.srl
            
            echo -e "${GREEN}✅ 客户端证书生成完成 (由CA签发)${RESET}"
            echo -e "${CYAN}   无密码版本: client.key, client.p12 (用于 4003 端口)${RESET}"
            echo -e "${CYAN}   带密码版本: client_encrypted.key, client_encrypted.p12 (用于 4002 端口, 密码: 123456)${RESET}"
        else
            echo -e "${GREEN}✅ 客户端证书已存在${RESET}"
        fi
        
        cd ..
        echo ""
        
        # 构建镜像
        echo -e "${CYAN}🔨 构建镜像...${RESET}"
        ./build.image.sh
        
        echo ""
        echo -e "${CYAN}🚀 启动容器...${RESET}"
        echo ""
        ./start.container.sh
        ;;
        
    3)
        echo -e "${CYAN}============================================${RESET}"
        echo -e "${CYAN}  本地运行模式${RESET}"
        echo -e "${CYAN}============================================${RESET}"
        echo ""
        
        # 检查依赖
        echo -e "${CYAN}🔍 检查依赖...${RESET}"
        
        # 检查 Node.js
        if ! command -v node &> /dev/null; then
            echo -e "${RED}❌ Node.js 未安装${RESET}"
            echo -e "   请安装 Node.js: https://nodejs.org/"
            exit 1
        fi
        echo -e "${GREEN}✅ Node.js: $(node --version)${RESET}"
        
        # 检查 Go
        if ! command -v go &> /dev/null; then
            echo -e "${RED}❌ Go 未安装${RESET}"
            echo -e "   请安装 Go: https://golang.org/"
            exit 1
        fi
        echo -e "${GREEN}✅ Go: $(go version)${RESET}"
        
        # 检查 OpenSSL
        if ! command -v openssl &> /dev/null; then
            echo -e "${RED}❌ OpenSSL 未安装${RESET}"
            exit 1
        fi
        echo -e "${GREEN}✅ OpenSSL: $(openssl version)${RESET}"
        
        echo ""
        
        # 生成证书（包括客户端证书）
        echo -e "${CYAN}📝 生成证书 (服务器IP: ${SERVER_IP})...${RESET}"
        mkdir -p cert
        cd cert
        
        # 生成服务器证书
        if [ ! -f "server.crt" ]; then
            # 构建 SAN 扩展（包含服务器IP）
            SAN_EXT="DNS:localhost,DNS:*.local,IP:127.0.0.1,IP:0.0.0.0"
            if [ "$SERVER_IP" != "localhost" ] && [ "$SERVER_IP" != "127.0.0.1" ]; then
                SAN_EXT="${SAN_EXT},IP:${SERVER_IP}"
            fi
            
            openssl req -x509 -newkey rsa:2048 -nodes \
                -keyout server.key -out server.crt -days 365 \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS/CN=${SERVER_IP}" \
                -addext "subjectAltName=${SAN_EXT}" 2>/dev/null
            echo -e "${GREEN}✅ 服务器证书生成完成 (IP: ${SERVER_IP})${RESET}"
        else
            echo -e "${GREEN}✅ 服务器证书已存在${RESET}"
        fi
        
        # 创建 ca.crt（用于双向认证）
        if [ ! -f "ca.crt" ]; then
            cp server.crt ca.crt
            cp server.key ca.key
            echo -e "${GREEN}✅ CA证书创建完成 (复制自server.crt)${RESET}"
        fi
        
        # 生成客户端证书（由CA签发）
        if [ ! -f "client.crt" ]; then
            # 生成客户端私钥和CSR
            openssl req -newkey rsa:2048 -nodes \
                -keyout client.key \
                -out client.csr \
                -subj "/C=CN/ST=Test/L=Test/O=OHOS Client/CN=client" 2>/dev/null
            
            # 使用CA签发客户端证书
            openssl x509 -req -in client.csr \
                -CA ca.crt -CAkey ca.key \
                -CAcreateserial -out client.crt \
                -days 365 2>/dev/null
            
            # 生成带密码的客户端私钥（密码: 123456）
            openssl rsa -des3 -in client.key -out client_encrypted.key -passout pass:123456 2>/dev/null
            
            # 生成无密码的 P12 证书包（用于 4003 端口）
            openssl pkcs12 -export -out client.p12 \
                -inkey client.key \
                -in client.crt \
                -certfile ca.crt \
                -passout pass: 2>/dev/null
            
            # 生成带密码的 P12 证书包（用于 4002 端口，密码: 123456）
            # 使用加密的私钥 client_encrypted.key，需要 -passin 读取私钥密码
            openssl pkcs12 -export -out client_encrypted.p12 \
                -inkey client_encrypted.key \
                -passin pass:123456 \
                -in client.crt \
                -certfile ca.crt \
                -passout pass:123456 2>/dev/null
            
            # 清理临时文件
            rm -f client.csr ca.srl
            
            echo -e "${GREEN}✅ 客户端证书生成完成 (由CA签发)${RESET}"
            echo -e "${CYAN}   无密码版本: client.key, client.p12 (用于 4003 端口)${RESET}"
            echo -e "${CYAN}   带密码版本: client_encrypted.key, client_encrypted.p12 (用于 4002 端口, 密码: 123456)${RESET}"
        else
            echo -e "${GREEN}✅ 客户端证书已存在${RESET}"
        fi
        
        cd ..
        echo ""
        
        echo -e "${CYAN}🚀 启动服务器...${RESET}"
        ./manage_servers.sh start all
        ;;
        
    *)
        echo -e "${RED}❌ 无效的选择${RESET}"
        exit 1
        ;;
esac

echo ""
echo -e "${CYAN}============================================${RESET}"
echo -e "${GREEN}${BOLD}  🎉 部署完成！${RESET}"
echo -e "${CYAN}============================================${RESET}"
echo ""
echo -e "${CYAN}🌐 服务访问地址:${RESET}"
echo ""
echo -e "${GREEN}  HTTP/HTTPS 服务器${RESET}"
echo -e "  - HTTP:  http://${PUBLIC_IP}:4000"
echo -e "  - HTTPS: https://${PUBLIC_IP}:4001 (需忽略证书)"
echo ""
echo -e "${GREEN}  MQTT 服务器${RESET}"
echo -e "  - TCP:       ${PUBLIC_IP}:1883"
echo -e "  - WebSocket: ${PUBLIC_IP}:1882"
echo -e "  - Stats:     http://${PUBLIC_IP}:8080"
echo ""
echo -e "${GREEN}  Socket.IO 服务器${RESET}"
echo -e "  - HTTP:  http://${PUBLIC_IP}:3100"
echo -e "  - HTTPS: https://${PUBLIC_IP}:3101"
echo ""
echo -e "${GREEN}  其他服务${RESET}"
echo -e "  - DNS:    ${PUBLIC_IP}:5353 (UDP)"
echo -e "  - Static: http://${PUBLIC_IP}:4006 (证书下载)"
echo -e "  - Proxy:  ${PUBLIC_IP}:8005"
echo ""
echo -e "${GREEN}  📜 证书下载${RESET}"
echo -e "  - CA 证书:            http://${PUBLIC_IP}:4000/cert/ca.crt"
echo -e "  - 客户端证书:         http://${PUBLIC_IP}:4000/cert/client.crt"
echo -e "  ${CYAN}[无密码版本 - 用于 4003 端口]${RESET}"
echo -e "  - 客户端私钥:         http://${PUBLIC_IP}:4000/cert/client.key"
echo -e "  - P12证书包:          http://${PUBLIC_IP}:4000/cert/client.p12"
echo -e "  ${CYAN}[带密码版本 - 用于 4002 端口, 密码: 123456]${RESET}"
echo -e "  - 加密客户端私钥:     http://${PUBLIC_IP}:4000/cert/client_encrypted.key"
echo -e "  - 加密P12证书包:      http://${PUBLIC_IP}:4000/cert/client_encrypted.p12"
echo -e "  ${CYAN}[其他]${RESET}"
echo -e "  - 证书包(JSON):       http://${PUBLIC_IP}:4000/cert/client-bundle"
echo -e "  - 证书列表:           http://${PUBLIC_IP}:4000/cert/list"
echo ""
echo -e "${GREEN}  📖 API 文档${RESET}"
echo -e "  - Swagger UI:     http://${PUBLIC_IP}:4000/api-docs"
echo ""
echo -e "${CYAN}⚠️  防火墙配置:${RESET}"
echo -e "   请确保以下端口已开放:"
echo -e "   TCP: 1882, 1883, 3100, 3101, 4000-4006, 8005, 8080"
echo -e "   UDP: 5353 (DNS)"
echo ""
echo -e "${CYAN}🔧 管理命令:${RESET}"

if [ "$DEPLOY_MODE" = "1" ]; then
    echo -e "   docker-compose logs -f     # 查看日志"
    echo -e "   docker-compose restart     # 重启"
    echo -e "   docker-compose stop        # 停止"
    echo -e "   docker-compose down        # 停止并删除"
elif [ "$DEPLOY_MODE" = "2" ]; then
    echo -e "   docker logs -f ohos-servers    # 查看日志"
    echo -e "   docker restart ohos-servers    # 重启"
    echo -e "   docker stop ohos-servers       # 停止"
else
    echo -e "   ./manage_servers.sh status     # 查看状态"
    echo -e "   ./manage_servers.sh stop all   # 停止所有"
    echo -e "   ./manage_servers.sh logs mqtt  # 查看日志"
fi

echo ""
echo -e "${GREEN}✨ 祝您使用愉快！${RESET}"
echo ""
